package com.hyt.it.ogt.pj.service.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hyt.core.enums.DelFlagEnum;
import com.hyt.core.util.FastJsonUtil;
import com.hyt.it.ogt.pj.enums.PaperItemViewPointEnums;
import com.hyt.it.ogt.pj.mapper.ItemScoreMapper;
import com.hyt.it.ogt.pj.mapper.PaperItemMapper;
import com.hyt.it.ogt.pj.mapper.PaperMapper;
import com.hyt.it.ogt.pj.mapper.PieceScoreMapper;
import com.hyt.it.ogt.pj.mapper.ProjectMapper;
import com.hyt.it.ogt.pj.mapper.StudentConfigMapper;
import com.hyt.it.ogt.pj.mapper.StudentMapper;
import com.hyt.it.ogt.pj.mapper.SubjectMapper;
import com.hyt.it.ogt.pj.mapper.SubjectScoreMapper;
import com.hyt.it.ogt.pj.mapper.TaskMapper;
import com.hyt.it.ogt.pj.model.entity.ItemScore;
import com.hyt.it.ogt.pj.model.entity.Paper;
import com.hyt.it.ogt.pj.model.entity.PaperItem;
import com.hyt.it.ogt.pj.model.entity.PieceScore;
import com.hyt.it.ogt.pj.model.entity.Project;
import com.hyt.it.ogt.pj.model.entity.Student;
import com.hyt.it.ogt.pj.model.entity.StudentConfig;
import com.hyt.it.ogt.pj.model.entity.Subject;
import com.hyt.it.ogt.pj.model.entity.SubjectScore;
import com.hyt.it.ogt.pj.model.entity.Task;
import com.hyt.it.ogt.pj.model.vo.SynCandidateConfigVo;
import com.hyt.it.ogt.pj.model.vo.SynCandidateInfoVo;
import com.hyt.it.ogt.pj.model.vo.SynDataVo;
import com.hyt.it.ogt.pj.model.vo.SynStemInfoVo;
import com.hyt.it.ogt.pj.model.vo.SynSubjectInfoVo;
import com.hyt.it.ogt.pj.service.ISynDataService;

import cn.hutool.core.collection.CollUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * <p>
 * 同步数据 服务实现类
 * </p>
 *
 * @author liy
 * @since 2022-03-11
 */
@Service
@Slf4j
public class SynDataServiceImpl implements ISynDataService {

    @Autowired
    private TaskMapper taskMapper;

    @Autowired
    private ProjectMapper projectMapper;

    @Autowired
    private StudentMapper studentMapper;

    @Autowired
    private PaperItemMapper paperItemMapper;

    @Autowired
    private PaperMapper paperMapper;

    @Autowired
    private StudentConfigMapper studentConfigMapper;

    @Autowired
    private PieceScoreMapper pieceScoreMapper;

    @Autowired
    private SubjectMapper subjectMapper;

    @Autowired
    private SubjectScoreMapper subjectScoreMapper;

    @Autowired
    private ItemScoreMapper itemScoreMapper;

    @Override
    public SynDataVo synDataToCJ(String taskId) {
        Task task = taskMapper.selectById(taskId);
        if (null == task) {
            return null;
        }
        // 查询评卷项目
        Project project = projectMapper.selectById(task.getProjectId());
        if (null == project) {
            return null;
        }
        // 查询科目信息
        Subject subject = subjectMapper.selectByProjectIdAndSubjectId(project.getId(), task.getSubjectId());
        if (null == subject) {
            return null;
        }

        // 获取考生信息
        QueryWrapper<Student> studentWrapper = new QueryWrapper<>();
            studentWrapper.lambda().eq(Student::getProjectId, task.getProjectId())
                                   .eq(Student::getSubjectId, task.getSubjectId())
                                   .eq(Student::getAdmissionNum, task.getEncodeId())
                                   .eq(Student::getDelFlag, DelFlagEnum.NORMAL.getCode())
                                   .last("LIMIT 1");
        Student student= studentMapper.selectOne(studentWrapper);
        if (null == student) {
            return null;
        }

        // 获取考生的试卷
        Paper paper = paperMapper.selectById(student.getPaperId());

        // 获取科目分数
        QueryWrapper<SubjectScore> subjectScoreWrapper = new QueryWrapper<>();
            subjectScoreWrapper.lambda().eq(SubjectScore::getProjectId, task.getProjectId())
                                        .eq(SubjectScore::getSubjectId, task.getSubjectId())
                                        .eq(SubjectScore::getEncodeId, task.getEncodeId());
        List<SubjectScore> subjectScores = subjectScoreMapper.selectList(subjectScoreWrapper);

        // 获取考生配置
        QueryWrapper<StudentConfig> studentConfigWrapper = new QueryWrapper<>();
            studentConfigWrapper.lambda().eq(StudentConfig::getProjectId, task.getProjectId())
                                         .eq(StudentConfig::getAdmissionNum, task.getEncodeId())
                                         .eq(StudentConfig::getCandidateId, student.getCandidateId());
        List<StudentConfig> studentConfigs = studentConfigMapper.selectList(studentConfigWrapper);
        
        // 获取评卷块
        QueryWrapper<PieceScore> pieceScoreWrapper = new QueryWrapper<>();
            pieceScoreWrapper.lambda().eq(PieceScore::getTaskId, task.getId())
                                      .eq(PieceScore::getEncodeId, task.getEncodeId())
                                      .last("LIMIT 1");
        PieceScore pieceScore = pieceScoreMapper.selectOne(pieceScoreWrapper);
        
        // 构建同步实体
        return buildSynDataVo(task, project, student, subject, pieceScore, paper, subjectScores, studentConfigs);
    }


    private SynDataVo buildSynDataVo(Task task, Project project, Student student, Subject subject, PieceScore pieceScore, Paper paper, List<SubjectScore> subjectScores,
                                     List<StudentConfig> studentConfigs) {
        // 只推送现考现评的考生数据
        SynDataVo synDataVo = new SynDataVo();
        synDataVo.setAdmissionNo(task.getAdmissionNum());
        synDataVo.setBeginTime(project.getBeginDate());
        synDataVo.setCandidateConfig(buildSynCandidateConfigVo(studentConfigs));
        synDataVo.setCandidateId(student.getCandidateId());
        synDataVo.setCandidateInfo(buildSynCandidateInfoVo(studentConfigs));
        synDataVo.setCityCode(student.getCityCode());
        synDataVo.setCountryCode(student.getDistrictCode());
        synDataVo.setExamId(project.getId());
        synDataVo.setExamName(project.getProjectName());
        synDataVo.setKeepHighestScore(false);
        synDataVo.setOfficeId(project.getOfficeId());
        synDataVo.setDeptId(project.getDeptId());
        synDataVo.setProvinceCode(student.getProvinceCode());
        // 现考现评默认传0。不设置合格分数线
        synDataVo.setScoreLine(BigDecimal.ZERO);
        synDataVo.setSubjectInfo(buildSynSubjectInfoVo(paper, pieceScore, subjectScores, subject, task));
        synDataVo.setTaskBeginDate(project.getBeginDate());
        synDataVo.setTaskEndDate(project.getEndDate());
        synDataVo.setTaskId(project.getTaskId());
        synDataVo.setTaskName(project.getTaskName());
        // 企业招聘考试，默认
        synDataVo.setTestClassify(StringUtils.isBlank(project.getExamType()) ? "" : project.getExamType());
        if (null != pieceScore) {
            synDataVo.setUseTime(null != pieceScore.getDuration() ? pieceScore.getDuration().longValue() : Long.valueOf(0L));
        }
        return synDataVo;
    }
    
    
    private List<SynCandidateConfigVo> buildSynCandidateConfigVo(List<StudentConfig> studentConfigs) {
        if (CollectionUtils.isEmpty(studentConfigs)) {
            return Collections.emptyList();
        }
        List<SynCandidateConfigVo> synCandidateConfigVos = new ArrayList<>(studentConfigs.size());
        for (StudentConfig studentConfig : studentConfigs) {
            SynCandidateConfigVo synCandidateConfigVo = new SynCandidateConfigVo();
            synCandidateConfigVo.setCode(studentConfig.getConfigId());
            synCandidateConfigVo.setName(studentConfig.getConfigCode());
            synCandidateConfigVos.add(synCandidateConfigVo);
        }
        if (!CollectionUtils.isEmpty(synCandidateConfigVos)) {
            return synCandidateConfigVos;
        }
        return Collections.emptyList();
    }

    private List<SynCandidateInfoVo> buildSynCandidateInfoVo(List<StudentConfig> studentConfigs) {
        if (CollUtil.isEmpty(studentConfigs)) {
            return Collections.emptyList();
        }
        List<SynCandidateInfoVo> synCandidateInfoVos = new ArrayList<>(studentConfigs.size());
        for (StudentConfig studentConfig : studentConfigs) {
            SynCandidateInfoVo synCandidateInfoVo = new SynCandidateInfoVo();
            synCandidateInfoVo.setConfigCode(studentConfig.getConfigId());
            synCandidateInfoVo.setConfigValue(studentConfig.getConfigValue());
            if (StringUtils.isNotEmpty(studentConfig.getConfigId())) {
                synCandidateInfoVo.setOrderNum(Integer.valueOf(studentConfig.getConfigId()));
            }
            synCandidateInfoVos.add(synCandidateInfoVo);
        }
        if (CollUtil.isNotEmpty(synCandidateInfoVos)) {
            return synCandidateInfoVos;
        }
        return Collections.emptyList();
    }

    private List<SynSubjectInfoVo> buildSynSubjectInfoVo(Paper paper, PieceScore pieceScore, List<SubjectScore> subjectScores,
                                                         Subject subject, Task task) {
        List<SynSubjectInfoVo> synSubjectInfoVos = new ArrayList<>(1);
        if (CollUtil.isNotEmpty(subjectScores)) {
            for (SubjectScore subjectScore : subjectScores) {
                SynSubjectInfoVo synSubjectInfoVo = new SynSubjectInfoVo();
                if (null != paper) {
                    BigDecimal paperFullScore = BigDecimal.ZERO;
                    if (null != paper.getPaperScore()) {
                        paperFullScore = paperFullScore.add(paper.getPaperScore());
                    }
                    synSubjectInfoVo.setPaperFullScore(paperFullScore);
                    synSubjectInfoVo.setPaperSort(paper.getSort());
                    synSubjectInfoVo.setStemList(buildSynStemInfoVo(paper, task));
                }
                BigDecimal paperScore = BigDecimal.ZERO;
                // 设置主观题分数
                if (subjectScore.getSubjectiveScore() != null) {
                    paperScore = paperScore.add(subjectScore.getSubjectiveScore());
                }
                // 如果主观题分数和小题主观题分数不一致则设置小题的主观题分数
                if (subjectScore.getSubjectiveScore() != null && subjectScore.getChildSubjectiveScore() != null && !subjectScore.getSubjectiveScore().equals(subjectScore.getChildSubjectiveScore())) {
                    paperScore = paperScore.add(subjectScore.getChildSubjectiveScore());
                }
                if (subjectScore.getObjectiveScore() != null) {
                    paperScore = paperScore.add(subjectScore.getObjectiveScore());
                }
                synSubjectInfoVo.setPapertScore(paperScore);
                if (null != pieceScore) {
                    synSubjectInfoVo.setPaperTimeLength(null != pieceScore.getDuration() ? pieceScore.getDuration().longValue() : Long.valueOf(0L));
                    synSubjectInfoVo.setPaperUseTime(null != pieceScore.getDuration() ? pieceScore.getDuration().longValue() : Long.valueOf(0L));
                    synSubjectInfoVo.setRemarks(pieceScore.getComment());
                }
                synSubjectInfoVo.setSubjectCode(subject.getSubjectId());
                synSubjectInfoVo.setSubjectName(subject.getSubjectName());
                // 默认普通卷
                synSubjectInfoVo.setSubjectType(1);
                synSubjectInfoVos.add(synSubjectInfoVo);
            }
        }

        return synSubjectInfoVos;
    }


    public List<SynStemInfoVo> buildSynStemInfoVo(Paper paper, Task task) {
        if (null == paper) {
            return Collections.emptyList();
        }
        try {
            log.info("buildSynStemInfoVo-paperId:{}", paper.getId());
            List<SynStemInfoVo> synStemInfoVos = new ArrayList<>();
            QueryWrapper<PaperItem> paperItemWrapper = new QueryWrapper<>();
            paperItemWrapper.lambda().eq(PaperItem::getPaperId, paper.getId()).eq(PaperItem::getItemViewPoint, PaperItemViewPointEnums.SUBJECTIVE_TYPE.getType()).eq(PaperItem::getParentId, '0');
            List<PaperItem> paperItems = paperItemMapper.selectList(paperItemWrapper);
            if (CollUtil.isEmpty(paperItems)) {
                return Collections.emptyList();
            }
            
            Map<String, PaperItem> paperItemMap = paperItems.stream().collect(Collectors.toMap(p -> p.getId(), PaperItem -> PaperItem, (key1, key2) -> key2));
            for (Map.Entry<String, PaperItem> entry : paperItemMap.entrySet()) {
                SynStemInfoVo synStemInfoVo = new SynStemInfoVo();
                synStemInfoVo.setStemId(entry.getValue().getTopicId());
                synStemInfoVo.setStemName(entry.getValue().getItemName());
                synStemInfoVo.setStemSort(entry.getValue().getOrderNum());
                //大题得分
                synStemInfoVo.setStemScore(BigDecimal.ZERO);

                // 迭代每一个大题
                List<PaperItem> chileItems = iteratorPaperItem(paper.getId(), entry.getValue().getId());

                if (CollectionUtils.isEmpty(chileItems)) {
                    continue;
                }
                Set<String> itemIds = chileItems.stream().map(chileItem -> chileItem.getId()).collect(Collectors.toSet());
                log.info("chileItems的ids:{}", FastJsonUtil.getBeanToJson(itemIds));
                List<ItemScore> itemScores = null;
                if (CollUtil.isNotEmpty(itemIds)) {
                    QueryWrapper<ItemScore> itemScorerapper = new QueryWrapper<>();
                    itemScorerapper.lambda().eq(ItemScore::getTaskId, task.getId()).in(ItemScore::getItemId, itemIds);
                    itemScores = itemScoreMapper.selectList(itemScorerapper);
                }

                if (CollUtil.isNotEmpty(itemScores)) {
                    Map<String, List<ItemScore>> itemScoreMap = itemScores.stream().collect(Collectors.groupingBy(i -> i.getUserId() + i.getEncodeId()));
                    BigDecimal stemScore = itemScores.stream().filter(i -> null != i.getScore()).map(ItemScore::getScore).reduce(BigDecimal.ZERO, BigDecimal::add);
                    if (MapUtils.isNotEmpty(itemScoreMap)) {
                        stemScore = stemScore.divide(new BigDecimal(itemScoreMap.size()));
                    }
                    synStemInfoVo.setStemScore(stemScore);
                }
                synStemInfoVos.add(synStemInfoVo);
            }
            return synStemInfoVos;
        } catch (Exception e) {
            log.error("方法buildSynStemInfoVo异常:{}", e);
        }
        return Collections.emptyList();
    }

    public List<PaperItem> iteratorPaperItem(String paperId, String parentId) {
        List<PaperItem> chileItems = paperItemMapper.selectByPaperIdByParentId(paperId, parentId);
        if (CollectionUtils.isEmpty(chileItems)) {
            return Collections.emptyList();
        }
        for (PaperItem index : chileItems) {
            List<PaperItem> tempPaperItems = iteratorPaperItem(paperId, index.getId());
            if (!CollectionUtils.isEmpty(tempPaperItems)) {
                chileItems.addAll(tempPaperItems);
            }
        }

        return chileItems;
    }


    /**
     * 构建汇总系统评卷数据同步成绩系统实体数据
     * @see com.hyt.it.ogt.pj.service.ISynDataService#hzSynDataToCJ(java.lang.String)
     **/
    @Override
    public SynDataVo hzSynDataToCJ(String taskId) {
        // 评卷任务
        Task task = taskMapper.selectById(taskId);
        if (null == task) {
            return null;
        }
        // 查询评卷项目
        Project project = projectMapper.selectById(task.getProjectId());
        if (null == project) {
            return null;
        }
        // 查询科目信息
        Subject subject = subjectMapper.selectByProjectIdAndSubjectId(project.getId(), task.getSubjectId());
        if (null == subject) {
            return null;
        }

        // 获取考生信息
        QueryWrapper<Student> studentWrapper = new QueryWrapper<>();
            studentWrapper.lambda().eq(Student::getProjectId, task.getProjectId())
                                   .eq(Student::getSubjectId, task.getSubjectId())
                                   .eq(Student::getAdmissionNum, task.getEncodeId())
                                   .eq(Student::getDelFlag, DelFlagEnum.NORMAL.getCode())
                                   .last("LIMIT 1");
        Student student= studentMapper.selectOne(studentWrapper);
        if (null == student) {
            return null;
        }

        // 获取考生的试卷
        Paper paper = paperMapper.selectById(student.getPaperId());

        // 获取科目分数
        QueryWrapper<SubjectScore> subjectScoreWrapper = new QueryWrapper<>();
            subjectScoreWrapper.lambda().eq(SubjectScore::getProjectId, task.getProjectId())
                                        .eq(SubjectScore::getSubjectId, task.getSubjectId())
                                        .eq(SubjectScore::getEncodeId, task.getEncodeId());
        List<SubjectScore> subjectScores = subjectScoreMapper.selectList(subjectScoreWrapper);

        // 获取考生配置
        QueryWrapper<StudentConfig> studentConfigWrapper = new QueryWrapper<>();
            studentConfigWrapper.lambda().eq(StudentConfig::getProjectId, task.getProjectId())
                                         .eq(StudentConfig::getAdmissionNum, task.getEncodeId())
                                         .eq(StudentConfig::getCandidateId, student.getCandidateId());
        List<StudentConfig> studentConfigs = studentConfigMapper.selectList(studentConfigWrapper);
        
        // 获取评卷块
        QueryWrapper<PieceScore> pieceScoreWrapper = new QueryWrapper<>();
            pieceScoreWrapper.lambda().eq(PieceScore::getTaskId, task.getId())
                                      .eq(PieceScore::getEncodeId, task.getEncodeId())
                                      .last("LIMIT 1");
        PieceScore pieceScore = pieceScoreMapper.selectOne(pieceScoreWrapper);
        
        // 构建同步实体
        return hzBuildSynDataVo(task, project, student, subject, pieceScore, paper, subjectScores, studentConfigs);
    }
    
    
    private SynDataVo hzBuildSynDataVo(Task task, Project project, Student student, Subject subject, PieceScore pieceScore, Paper paper, List<SubjectScore> subjectScores, List<StudentConfig> studentConfigs) {
        // 只推送现考现评的考生数据
        SynDataVo synDataVo = new SynDataVo();
        synDataVo.setAdmissionNo(task.getAdmissionNum());
        synDataVo.setBeginTime(project.getBeginDate());
        synDataVo.setCandidateConfig(buildSynCandidateConfigVo(studentConfigs));
        // candidateid暂时设置为考生的id，后续如果有要用这个数据再优化【要不要把考务的id对应上】
        synDataVo.setCandidateId(student.getId());
        synDataVo.setCandidateInfo(buildSynCandidateInfoVo(studentConfigs));
        synDataVo.setCityCode(student.getCityCode());
        synDataVo.setCountryCode(student.getDistrictCode());
        synDataVo.setExamId(project.getId());
        synDataVo.setExamName(project.getProjectName());
        synDataVo.setKeepHighestScore(false);
        synDataVo.setOfficeId(project.getOfficeId());
        synDataVo.setDeptId(project.getDeptId());
        synDataVo.setProvinceCode(student.getProvinceCode());
        // 现考现评默认传0。不设置合格分数线
        synDataVo.setScoreLine(BigDecimal.ZERO);
        synDataVo.setSubjectInfo(buildSynSubjectInfoVo(paper, pieceScore, subjectScores, subject, task));
        synDataVo.setTaskBeginDate(project.getBeginDate());
        synDataVo.setTaskEndDate(project.getEndDate());
        synDataVo.setTaskId(project.getTaskId());
        synDataVo.setTaskName(project.getTaskName());
        // 企业招聘考试，默认
        synDataVo.setTestClassify(StringUtils.isBlank(project.getExamType()) ? "" : project.getExamType());
        if (null != pieceScore) {
            synDataVo.setUseTime(null != pieceScore.getDuration() ? pieceScore.getDuration().longValue() : Long.valueOf(0L));
        }
        return synDataVo;
    }

}
